package cn.yeziji.utils;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.util.Arrays;
import java.util.Optional;

/**
 * @author gzkemays
 * @date 2021/1/25 16:30
 */
public class AesUtils {
    private AesUtils() {}

    private static final String ALGORITHM = "AES";
    private static final String CHARSET_NAME = "UTF-8";

    /**
     * 	加密
     * @param data - 加密数据
     * @return - 返回加密后的字符串
     * @throws GeneralSecurityException
     */
    public static String encrypt(String data) throws GeneralSecurityException {
        return encrypt(data, null);
    }

    /**
     * 	解密
     * @param data - 加密字符串
     * @return - 解密字符串
     * @throws GeneralSecurityException
     */
    public static String decrypt(String data) throws GeneralSecurityException {
        String  decryptData = decrypt(data, null);
        return decryptData;
    }

    /**
     * 	根据key字符串加密
     * @param data - 加密数据
     * @param key  - 盐值
     * @return - 返回加密后的字符串
     * @throws GeneralSecurityException
     */
    public static String encrypt(String data, String key)
            throws GeneralSecurityException {
        try {
            key = getSecrtKey(key);
            Key k = toKey(Base64.decodeBase64(key));
            byte[] raw = k.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(1, secretKeySpec);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET_NAME));
            return Base64.encodeBase64String(bytes);
        } catch (UnsupportedEncodingException e) {
            // 不支持的编码异常
            return data;
        }

    }

    /**
     *	 根据key解密字符串
     * @param data - 加密字符串
     * @param key  - 盐值
     * @return - 返回解密后的字符串
     * @throws GeneralSecurityException
     */
    public static String decrypt(String data, String key)
            throws GeneralSecurityException {
        try {
            key = getSecrtKey(key);
            Key k = toKey(Base64.decodeBase64(key));
            byte[] raw = k.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(2, secretKeySpec);
            byte[] baseData = Base64.decodeBase64(data);
            if (baseData.length == 0) {
                throw new RuntimeException("数据无法通过Base64解码");
            }
            byte[] bytes = cipher.doFinal(baseData);
            return new String(bytes, CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            // 不支持的编码异常
            return data;
        }

    }

    private static Key toKey(byte[] key) {
        SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
        return secretKey;
    }

    private static String getSecrtKey(String encrypted) throws UnsupportedEncodingException {
        encrypted = Optional.ofNullable(encrypted).orElse(AesUtils.class.getName());
        byte[] bytes = encrypted.getBytes(CHARSET_NAME);
        bytes = Arrays.copyOf(bytes, 16);
        return Base64.encodeBase64String(bytes);
    }
}
